Blocking and Non-Blocking: Asynchronous Nature of Node.js
Let’s now take a minute to learn about the asynchronous nature of Node.js, which includes absolutely fundamental topics, like synchronous, asynchronous, blocking, and non-blocking code. And all of this will be really important in order to understand everything that’s coming up throughout this section.
So this piece of code that we wrote in the last lecture, to read a file and then, save it’s content into a variable, was in a so-called synchronous way, which simply means that each statement is basically processed one after another, line by line.
In this example, first, the file system module is required, then, the file is read, and then, we log the result to the console. So you see that each line of code basically waits for the result of the previous line. Now, this can become a problem, especially with slow operations, because each line blocks the execution of the rest of the code.And so, we say that synchronous code is also called blocking code because, again, a certain operation can only be executed after the one before has finished. And because of the way Node.js was designed, this turns into a huge problem, as we’ll see in detail in the next slide.
So the solution to this problem in Node is to use asynchronous, non-blocking code. So in asynchronous code, we upload heavy work to basically be worked on in the background. And then, once that work is done, a callback function that we register before is called to handle the result. And during all that time, the rest of the code can still be executing without being blocked by the heavy task, which is now running in the background. So what this means is that we can effectively defer or reaction into the future in order to make the code non-blocking and this is, of course, much better. Makes sense? So, in this example, we use the asynchronous readFile function, which accepts a callback function. This will start reading the file in the background and then, immediately move on to the next statement, printing to the console the string-reading file. So, again, you see, we are not blocking the execution here. Then, when the file is finally completely read, the callback function will be called, and so, the data that was read will then be printed to the console. So that’s quite different from the synchronous version, isn’t it?
Now, the question here is, why does is actually have to be this way? What’s the problem with blocking code execution in Node.js? Or, in other words, why do we actually use callback so many times in Node.js?
Well, let’s find out. And in order to understand these questions, the first thing that we need to understand is the fact that a Node.js process, which is where our application is running, there’s only one single thread. And the thread is just like a set of instructions that is run in the computer’s CPU. So basically, the thread is where our code is actually executed in a machine’s processor. So, remember, Node.js is basically single-threaded and so, for each application, there’s only one thread. That’s just the way Node.js was designed.
Now, what that means is that all the users accessing your application are all using the same thread, so, basically, accessing the same thread. And so, whenever they’re interacting with the application, the code that is run for each user will be executed all in the same thread at the same place in the computer running the application. And that is true no matter if you have five users, like in this diagram, or 5,000 or 5 million. All right?
Now, what this also means is that when one user locks the single thread with synchronous code, like we just saw before, then all other users will have to wait for that execution to finish.